package com.pop.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.Test;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;

/**
 * @author Pop
 * @date 2022/8/23 20:45
 *
 * 客户端代码常用套路
 *
 * 1、获取一个客户端对象
 * 2、执行相关的操作对象
 * 3、关闭资源
 */
public class HdfsClient {

    private FileSystem fileSystem;

    public void init()  throws Exception{
        // 连接的集群nn地址
        URI uri = new URI("hdfs://hadoop102:8020");
        // 创建一个配置文件
        Configuration configuration = new Configuration();
        // 配置
        configuration.set("dfs.replication","2");

        String user = "root";//指定用户
        // 获取客户端对象
        fileSystem = FileSystem.get(uri, configuration,
                user);

    }

    public void close() throws Exception{
        //关闭资源
        fileSystem.close();
    }

    @Test
    public void testmkdir() throws Exception {
        init();
        // 创建一个文件夹
        fileSystem.mkdirs(new Path("/xiyou/huaguo"));
        close();

    }

    // 上传

    /**
     * 配置文件优先级
     * 越后面优先级越高
     * hdfs-default.xml -> hdfs-site.xml -> 代码中的Configuration配置
     * @throws Exception
     */
    public void testPut() throws Exception{

        /**
         * delSrc，是否删除原数据
         * overwrite，是否覆盖目标数据
         * pahtString：需要拷贝的文件
         * pathString：拷贝后的文件
         */
        fileSystem.copyFromLocalFile(false,
                false,new Path("/1.txt"),
                new Path("./1.test"));
    }

    //文件的下载
    public void testGet() throws Exception{
        /**
         * 是否删除原文件
         *
         * 原文本hdfs路径
         *
         * 下载到哪里
         *
         * 是否开启本地校验
         * 如果在下载的文件的时候，会下载两个文件
         * 一个是你要下载的文件，一个是以.crc结尾的文件
         * 当你上传文件的时候，hdfs会对你的文件进行crc算法加密得到一个值
         * 存储在一个crc文件中。
         * 当你下载的时候，crc文件同时也会下载下来，hdfs会对你下载下来的文件
         * 再次进行crc算法，此算法和上传时是一样的，如果两个值计算
         * 相同，则意味着文件内容没有丢失
         * 如果不相同则意味着文件内容存在丢失。
         *
         * false 会开启校验
         *
         * true 不会开启，其实也就是会下载会附带一个crc文件的区别。
         */
        fileSystem.copyToLocalFile(false,
                new Path(""),
                new Path(""),false);
    }

    // 删除
    public void testRm() throws Exception{
        /**
         * 删除路径
         *
         * 是否递归删除
         */
        fileSystem.delete(new Path(""),false);

        // 删除空目录
        fileSystem.delete(new Path("/"),false);

        // 删除非空目录, 需要递归
        fileSystem.delete(new Path("/jinguo"),true);
    }

    public void testMv() throws Exception{
        /**
         *
         *  对文件名称修改
         * 原文件路径
         *
         * 目标文件路径
         */
        fileSystem.rename(new Path("./test.txt"),
                new Path("./test1.txt"));

        // 目录更名
        fileSystem.rename(
                new Path("/input"),
                new Path("/out")
        );
    }

    /**
     * 获取文件信息
     * 希望获取到和web9870一样的信息
     */
    public void fileDetail() throws IOException {
        // 获取所有文件信息
        RemoteIterator<LocatedFileStatus> locatedFileStatusRemoteIterator
                = fileSystem.listFiles(
                new Path("/"), true
        );
        while(locatedFileStatusRemoteIterator.hasNext()){

            LocatedFileStatus next = locatedFileStatusRemoteIterator.next();
        //路径
            System.out.println(next.getPath());
            //权限
            next.getPermission();
            next.getOwner();
            next.getGroup();
            next.getLen();
            next.getModificationTime();
            next.getReplication();
            next.getBlockSize();
            next.getPath().getName();

            // 获取块的信息
            BlockLocation[] blockLocations = next.getBlockLocations();
            System.out.println(Arrays.toString(blockLocations));
        }


    }

    // 判断是否是文件或者文件夹
    public void testFile() throws IOException {
        FileStatus[] fileStatuses = fileSystem.listStatus(new Path("/"));

        for (FileStatus status : fileStatuses) {
            // 是否是文件
            if (status.isFile()){

            }

            // 是否是目录
            if (status.isDirectory()){

            }
        }
    }
}
